Remote Administrator v1.11 Tutorial by cLUSTER! - 12th December 1999.


Now this is truly an excellent piece of software, the best of its kind
really, and it also has one of the most interesting protection schemes
I've come across so far.

But even though Dmitry Znosko has put a lot of effort into making this
application virtually uncrackable using traditional cracking approaches,
such as serial-fishing and code-patching, us reversers always come up with
new and brilliant ways of approaching our targets and find our ways about
to make it obey our will!

Still, this one has actually been on the stand before although none of the
former crackers have succeeded to make a 100% working crack.

The first attempt was made by someone in PGC, I don't remember who,
however, he failed miserably. He managed to remove the NAG, and it also
seemed registered, except for not showing any name and also saying 0 licenses.
Now, this we could have lived with, IF he had at least managed to remove the
checksums, which caused radmin to crash every time you added a new host or
tried to connect to a server. Such a crack is not of much use, disabling the
core functionality of the application.

The second attempt made by Staier (tutorial can be found on fravia) on how to
reverse this target by dumping the unpacked module and then disassembling it
using IDA might be an interesting way of doing it, but we still don't end up
with a fully registered application, instead it is still unregistered with the
annoying nag showing and without any name/licenses, only the expiration has
been removed. This method of reversing is too time consuming considering what
we can achieve using it and also that it is fairly easy to find the piece of
code that checks the registration using sice. But obviously that wasn't even
what Staier had in mind, instead he concentrated on removing only the expiration
checks, maybe because a deadlisting does not have any string references to where
the regflag for registration is located ;)

After numerous hours of analyzing the code and its bitching, I feel confident
to say that I found a truly excellent way of terminating the need for any
registration code or even any patched code.

Turn On, Tune In and may this tutorial shed some light upon new ways to follow
in the art of reverse engineering..


Tools used: SoftIce, Custom Loader, Some Coke and Loads of Psychedelic Trance.


NOTE: This application uses relative addresses for its unpacked code, so the
      code-snippets addresses below might differ from the ones you will get
      when reversing radmin.


For starters, lets look at what we have here..  Running radmin for the first
time tells us that it is an "unregistered copy" and that we can unlock it
entering a registration code.

Now we feel all confident.. There is a way to make it registered using a
registration code.. This shouldn't be all that hard, should it?

So, we click Enter Code and a dialog box shows up, asking us for the
registration code.. Mhm.. No name.. Either this is gonna be quite easy
to fish.. Using hardcoded serial or maybe parts of the reg. code generates
the other parts of it.. Or if we're out of luck it is going to be a real
bitch of a protection using checksums, maybe even system id and who knows
what else...

Enough speculating, lets find out.. First we enter our registration code..

1234554321

Yeah, that's it.. This is nice combination of chars since it isn't very likely
to be laying around somewhere in memory already.

Now lets break into sice and put a breakpoint on hmemcpy.

BPX hmemcpy     ;the almighty undocumented feature especially implemented for
us reversers.. coming soon to a winnt/2k machine near you!  ...not!
                 
And then we click OK.

It breaks into sice. Yea yea, it always works damnit. We are so friggin' 3li7e! ;)

Since we don't usually enjoy F12'ing our way out of calls, let's just put a BPRW
on the processes name instead.. (use MOD to see names).. 

BPRW radmin     ;this causes softice to break when the applications code starts
                 to execute again.

Exit sice and let it rip.

WTF?.. Back to the application... Now what's this.. As I see it there are two
possible reason why sice didn't break. One is that the application is packed,
this is the most likely one.. Or it might even be crypted (breakpoint protected).
The other is that there is a second executable running that handles all the
checking that we missed out on.. Less likely since there is just 2 executables
installed and the other executable being the server. (It could not have been a
DLL/VXD, since sice catches all such calls).


Well, let's do it all over again.. This time using F12 instead of BPRW.

Success.. This time we end up at,

B46126 MOV EDI, [USER!EndDialog]   (I take for granted that you use exports.)

Now this is quite an odd memorylocation.. But still, it is part of Radmins
code.. (check lower right corner in sice)

Still, since I did bring up the subject on external DLL/VXD's used by the
application, let's have a look at which ones radmin uses.

QUERY radmin

Base  AllocBase   AllocProt   Size   State    Protect   Owner
-------------------------------------------------------------
....  ......      ..          ..     ..       ..     xxxxxxxx


While browsing through the Query status of radmin we should look at the
Owner (xxxxxxxx) to locate any used DLL/VXD's.

Nopes, nothing out of the ordinary.. Except for a whole lot of memory
space allocated for use and the ordinary Windows DLL's.

Out of curiosity we'll have a look at radmins bit sections to see if
there is any sections we recognize (of any known packers)..

MAP32 radmin

Owner    Obj Name   Obj #   Address          Size        Type
-------------------------------------------------------------
RADMIN   .TEXT      0001    0167:01401000    00008D46    CODE   RO
RADMIN   .RDATA     0002    016F:0140A000    00001952    IDATA  RO
RADMIN   .DATA      0003    016F:0140C000    0002c418    IDATA  RW
RADMIN   .RSRC      0004    016F:01439000    00025500    IDATA  RO
RADMIN   .RELOC     0005    016F:0145F000    00000A30    IDATA  RO


Nah.. These are all common section names from executables..

But looking at the section addresses tells us where radmins code is
mainly located (the packed code that is), and our current EIP being
B46126 confirms that we are indeed tracing a piece of unpacked code.

But what do we care?  We are gonna get ourselves a working reg. code.
and if we ever need to investigate what packer has been used, if any
known, we'd just use any of the existing exe analyzers. I'd recommend
File Analyzer since it has proven to detect most common packers and
also gets updated often. Radmin has it's very own packer though, so
none of the existing exe analyzer will detect any packer being used
with the executable.

Anyways, let's get with the program.. standard routine here.. we'll just
put a breakpoint-on-range on our reg.code string in memory and let radmin
run and we will probably end up in some comparison routine and we're all
set.. or maybe not.. Off we go..   (NOTE: BPR is not available in WinNT)

First of all we need to find out where our reg. code string is located in
memory.. Tracing a couple of lines and we'll end up at ...

B46135 MOV EDX, [ESP+C]

Do a D EDX to see memory contents.. ahh.. nice, there is our reg. code..

(Using sice's S cmd is also very useful to locate strings in memory.)

We'll do a BPR EDX EDX+A R to make sice break when radmin reads from our
reg.code string.

We exit sice and wait.. Several microseconds later, and we're back in action.

This time at...

B44618 MOV AL,[EBX]       ;moves 31 to AL  (31=1 from our string 1234554321)
...... XOR ESI,ESI
...... PUSH EDI
...... MOV EBP,EDX
...... TEST AL,AL         ;checks if there is anything in AL
...... JZ B446FC          ;if not, that is if we didn't enter any code, it jumps.
...... MOV CL, [EBX+1]    ;moves 32 to CL  (next char in our string)
...... TEST CL,CL         ;checks if there is anything in CL
...... JZ B446FC          ;if not, this is not a valid code, and it jumps.

B44634 CALL B8A14A

At this call we need to pay some attention..

When tracing into this call, some 280 kb higher in memory, we see yet another
call to a even higher address (4.5 mb higher).

B8A14A PUSH 0000001E
...... CALL FE0540


Radmin being 390 kb's in its original packed size, then the former piece of code
(b44xxx->b8axxx) makes sense when it comes to size in memory.. But, some 4.5 mbs
further up in memory doesn't. Seems as if radmin has been unpacking itself to
several locations in memory.. But let's not bother with this right now though..
On with the show...

Let's trace into the call..

FE0540 PUSH AD         (pushes all registers to the stack)


..
..
FE0571 XOR EAX, [EBX*4+008BD934]  ; checksums the code
..
..
loop back to  of code until done with range of addresses.
..
FE059D ADD EAX, D91A65C5  ; adds a static value to the checksum'd EAX value.
...... MOV EBX, [ESP+20]  ; moves out an address to EBX
...... SUB EBX, EAX       ; subs the address with what is left in EAX
...... MOV [ESP+24], EBX  ; moves the results of the sub to the stack.
...... POPAD              ; pops back all registers
...... RET                ; exits


Now what happens in the above code is that it points to an address of
radmins unpacked code and then loops, inc's address and does a checksum
on the code in each loop until it has completed the loop entirely..

Then it uses the checksum'd value, which if correct, will results in
the coming address to be executed when it has exited this call and the
previous one.

So, if we were to successfully unpack this piece of code (or just use an
inmemory patcher) and patched some of its code, radmin would crash since
the address it'd execute after the checksum routine would be way out
of radmins code.

Now I got you thinking.. "This guy sucks.. Nimas problemas.. I'll
just go ahead and patch these checksums.. Been there done that!.."

Not this time, this is a no can do situation. Since what we will see in the
coming CALL's we trace is that every piece of checksum code is unique.. 
It never uses the same static value once and that means we would have to
patch each and every one in their very own way.. Sure this is theoretically
possible.. But it'd be plain stupid!

Hold it.. Stop right there.. Now I got you thinking again..
"Fuck, this guy is seriously retarded.. It's easy.. Why patch the
checksum routine that contains the static value that is fucking us up?
I'll just go ahead and find out what address it calls once passing
the checksum, and then patch the call that jumps to checksummin'
code and make it call the correct piece of code directly..
This is no match for me..".

Bam Bam!.. General Protection Fault.. Since what we will also realize is that
EVERY piece of god damn code in this friggin' application gets checksummored.
That is, if you were to patch a single line of code, it'd trigger the checksum
that checks this particular range of addresses, and removing this checksum
as well would just trigger the next one.. and so on..

In other words, this application is a bitch to patch.. So we better hope there
is a good way of fishing/generating a valid reg. code.

Back to where we were tracing, that is, after the checksum code.

Code snippet of previous traced code -> current EIP ...

B44618 MOV AL,[EBX]       ;moves 31 to AL  (31=1 from our string 1234554321)
...... XOR ESI,ESI
...... PUSH EDI
...... MOV EBP,EDX
...... TEST AL,AL         ;checks if there is anything in AL
...... JZ B446FC          ;if not, that is if we didn't enter any code, it jumps.
...... MOV CL, [EBX+1]    ;moves 32 to CL  (next char in our string)
...... TEST CL,CL         ;checks if there is anything in CL
...... JZ B446FC          ;if not, this is not a valid code, and it jumps.

B44634 CALL B8A14A


B8A14A PUSH 0000001E
...... CALL FE0540
...... RET                <<<<<<<<<<<<<<<<<<   WE ARE HERE !!


After this ret, we will end up at the address the checksum ended up
with.

B441F0 MOVSX EAX, CL        ;CL=32
B441F3 ADD EAX, -2B         ;32 + -2B = 7
B441F6 CMP EAX, 4F          ;why this? well, 4F+2B = 7A ("z").
B441F9 JA B44380            ;not valid char, jumps.
B441FF JMP [EAX*4+00B44384] ;7*4+B44384 = [B443A0] = 0C 42 B4 -> B4 42 0C

B4420C MOV EAX, 00000002
B44214 RET

what the above code does is that it takes the second char in our string,
contained in CL from former code, which is 32h = "2", and when the relative
jump is made, the same decimal value is moved into EAX but now in hex form.

So, 31 -> 01 , 32 -> 02 ... etc..


After this ret we're back at main stream again.. Where we were before the
checksum call, at

B44639

from which it continues to checksum the entered reg. code, looping in a
huge piece of code until the entire reg. code string is done, ending up at

B44701


At this point it is time to ask ourselves what our approach to the situation
is going to be.. Are we going to spend hours and hours analyzing the code
that generates the checksum as well as the coming parts that will compare the
checksum'd result with checksums and checksum and checksums.... get real!
For fucks sake all we want to do is to beat this protection in ANY way and
make this application fully registered as well as functional.. Why put hours
or maybe days of hard work to eventually succeed in making a keygen for this
application. So far this applications protection has been pretty impressive,
so we can take for granted that reversing the protection scheme into being
able to generate our own valid reg. code(s) would be on the edge to insanity.

Nah, from here on we will try to locate where radmin compares our faulty
generated checksum-code with whatever and see if we can fool it some way..

I know, I know.. Patching the code won't be easy, but that is a problem
we will have to deal with later..

Back to reversing..


After B44701 where it makes a RET it steps back in the code flow to

B4614A MOV EAX, [ESP+8]         ; [ESP+8] = 81     (part of checksumming)
B4614E TEST EAX,EAX             ; checks if the reg. code checksumming function
                                  successfully executed.
B46150 JNZ B46157               ; if so, jump

B46157 MOV EDX, [ESP+8]         ; [ESP+8] = 81     (part of checksumming)
B4615B LEA ECX, [ESP+000003F4]  ; [ESP+000003F4] = Our regcode, in its
                                                   checksum'd format.
B46162 SHR EDX, 3               ; 81 -> 10   this is the length of our reg. code
                                             in checksum'd format.
B46165 CALL B8A2C0              ; This call creates a registry key
                                  \SOFTWARE\RAdmin\v1.01\ViewType\Data
                                  containing the checksum'd reg. code.
B4616A CALL B8A2CB              ; Gets the registry key reg. code.
..
..
B46177 CALL [USER32!SETDLGITEMTEXTA] 
B4617D PUSH 00
B4617F PUSH ESI
B46180 CALL EDI    ; Calls [USER32!ENDDIALOG]


Until the location above where it calls SetDlgItemTextA, still no
comparison with the checksum'd reg. code had taken place, and after
this call it was all over. The call to EndDialog ended it all.

I was a bit confused here but after some more investigation I found out that
the call to the final checking was made within the SetDlgItemTextA call itself.

Let's do the following to get to the code that gets called from inside the api..

S 0 l c0000000 "02345665432"     (take note, the first char is now an "0")

We'll find several memory locations with this string in it.

On two of these locations the string will look like this:

023455432100MyFt-L0j9--2

Here we put BPR's on those two addresses and then let radmin run again.

We will now end up in a loop that generates the checksum'd code.

(to those of you that have traced all code until this point, yes it is the same
 code as before that generated the checksum'd reg. code.)

Once in this loop we will F12 us out of this call.

Now we end up at B44914, from here forward until B44946 the actual comparisons
of the checksum'd code takes place.

Now, this is where things starts to get interesting again..

Let us have a look at some code snippets...

B44946 TEST EAX,EAX           ; Regflag test. Is it a valid checksum'd reg.code?
B44948 JNZ B44A4B             ; If not, jump!
B4494E MOV CL, [ESP+18]       ; Move a byte from [ESP+18] to CL
B44952 MOV AL, 16             ; Move 16 to AL
B44954 CMP CL, AL             ; Compare AL (16) with CL (00)
B44956 JNZ B44A4B             ; If not the same, jump!
B4495C CMP [ESP+19], AL       ; Compare [ESP+19], AL (16)
B44960 JNZ B44A4B             ; If not the same, jump!
B44966 CMP [ESP+1A], AL       ; ....
B4496A JNZ B44A4B             ; ....
B44970 CMP [ESP+1B], AL       ; ....
B44974 JNZ B44A4B             ; ....

Let's start with this part of the code..

First of all we must pass the regflag test, we'll do a R=0 for the
time being.

Next up, it compares the range [ESP+18 - ESP+1B] with 16's.

We'll simply E [ESP+18] at B4494E and enter four 16's there.


Tracing the next few lines leaves us clueless of what it wants,
so let us just exit softice and let radmin run and see what
happens.

Fucking great!.. It says Registered.. But, to noone and with 0 licenses..

Now this is not as great.. But wtf.. We're on a roll here, let's get
on with the reversing.. We might just get lucky? ;)

Let's have a look at what follows...

B4497A MOV EAX, [ESP+1E]      ; Moves a word from [ESP+1E] to EAX
B4497E MOV ECX, [ESP+1D]      ; Moves a word from [ESP+1D] to ECX
B44982 MOV EDX, [ESP+1C]      ; Moves a word from [ESP+1C] to EDX
B44986 AND EAX, 000000FF
B4498B SHL EAX, 08
B4498E AND ECX, 000000FF
B44994 AND EDX, 000000FF
B4499A ADD EAX, ECX
B4499C MOV ECX, [ESP+1F]      ; Moves a word from [ESP+1F] to ECX
B449A0 SHL EAX, 08
..
..

To quickly get a grip on what is happening here we will do some
trial & error.. We edit [ESP+1C - ESP+1F] and put four 11's there.

Now exit softice and let radmin run.

Ok, now we are kicking some serious asses.. Registered, and with 17 licenses..

After a few minutes of playing around with this particular memory location,
putting all kinds of different values there, we have successfully managed
to recreate a working license-string.

from [ESP+18 - ESP+1B] we should put 16's, this must be some kind of checksum.

from [ESP+1C - ESP+1E] does nothing

from [ESP+1F - ESP+20] decides how many licenses there should be (see table below)

from [ESP+21 -> ESP+21+xx UNTIL 00h] string to put after registered to:

from [ESP+xx (AFTER 00h) -> ESP+xx) string to put within the parenthesis.

Maximum length of the entire string is 3e8h = 1000.


Licenses table:

x x x x
-------
1         -     16 licenses
  1       -      1 licenses
    1     -   4096 licenses
      1   -    256 licenses
1 1       -     17 licenses
2         -     32 licenses
2   2     -   8224 licenses
F F F F   -  65535 licenses


So putting this string starting at [ESP+18] would make radmin registered
with maximum amount of licenses:

16 16 16 16 00 00 00 FF FF 43 4C 55 53 54 45 52 00 41 53 53 4B 49 43 4B 45 52


That's it.. Protection Terminated!..

That is if you feel like using sice everytime you want to use radmin..
And we wouldn't want that now would we?

What must be done is a sophisticated loader.. A kickass in-memory patcher..

And NO, you can NOT use any of the existing ones available on the net, since
they all lack features that makes it possible to patch apps such as this one.

I'm sorry to say that even though most of them have been undergoing development
for a long time and they still are very limited.

I will now explain how the loader I use to crack radmin with works, but I will
not be giving away any sources with this tutorial.

The reason for this is simple, I made this tutorial to show serious reversers
how to approach a target such as radmin, not to ruin the developers of radmin
by sharing all that is needed for people not being able to reverse a target
such as this one themselves.

If you are serious about using radmin you SHOULD buy it!.. The developer of
radmin deserves every penny he can get.. He has made an kickass application,
and he isn't asking for much, $25 is well worth spent money if you are
seriously going to use this application.



Loader approach
---------------
Our goal is to reach to the address of the regflag test and once we've
reached to this point, we need stop radmin from running and move the needed
bytes into memory and then resume the execution of radmins code.

To succeed in doing so, we need to implement the following features into our
loader:

- We must be able to put breakpoints in code and handle them.
- Read/Write Registers.


If you manage to make a loader with the above features, you will need to
take the following under consideration to make a fully working loader...

- The first breakpoint must be set relative to the start of the first
  unpacked code. Whenever you need to set new breakpoints, and you will
  have to do so since radmins code gets unwrapped progressively, you
  should keep in mind that you must put the breakpoints relative the start
  of the codeblock they belong to, which may be unpacked to different
  addresses each time the program is run...


Hints: The only static code that jumps to unpacked code is at 1401690.
       From here you should proceed with the next steps.
       
       Use BPR on the unpacked code to find out from where it gets
       unwrapped.

       If you by some reason manage to get radmin to expired and want to
       remove the expiration, edit HKLM -> Software and REMOVE the key
       named DATA.

       When putting breakpoints at code that is not yet existing in
       memory but is about to be unpacked and executed soon, you can
       not use BPX with the address, you MUST use BPM address X ..
       Also do not forget to use ADDR to change to the right process
       before putting any such breakpoints.


I hope that this tutorial was of any use.. I've tried to make this tutorial
as detailed as possible, so that not only the very best reversers could get
a grip on what is going on, but also the upcoming masters of the beautiful
art of reverse engineering.


Last but not least, I pay my deepest respects to MANMACHINE for not only
being a great friend but also for making advanced loaders/patchers and other
useful tools become a reality for me to use. I could never have made this one
without you!


Radmin Reversed & Tutorialized (c) Dec 1999 - [ cLUSTER! ]
Loader Coding [Src Unrevealed] (c) Dec 1999 - [ mANMACHiNE! ]